/**
 * @file shell.c
 * @author Rik Janssen
 *
 * @date 14-01-2011 DD-MM-YYYY
 * @version 0.4
 *
 * @section DESCRIPTION
 *
 * Client interface/shell.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "shell.h"
#include "connectionCmds.h"
#include "fileOperationsCmds.h"
#include "fileTransferCmds.h"
#include "otherCmds.h"

#define ERROR 1
#define NOERROR 0
#define MAXPARS 4
#define CMDLINELEN 255

/*Internal function prototyping*/
int getCommand(char *ptr_sCmdLine, int size);
int split(char *str, char *word[], int max, char c);
int execCommand(char *ptr_sCmdPars[]);

/**
 * Main function.
 *
 * @param argc Amount of args.
 * @param argv List of args.
 * @return -1 on error and 0 on no error.
 * @author Rik Janssen
 */
int main(int argc, char** argv)
{
    char sCmdLine[CMDLINELEN], *ptr_sCmdPars[MAXPARS];
    int i;

    /*Eternal loop*/
    while(1) {
        /*Reset command and pars to NULL*/
        for(i=0; i<MAXPARS; i++)
            ptr_sCmdPars[i] = 0;

        /*Get input from command line*/
        if(getCommand(sCmdLine, CMDLINELEN))
            fprintf(stderr, "Error when reading command!\n");
        else {
            /*Seperate command and parameters*/
            split(sCmdLine, ptr_sCmdPars, MAXPARS, ' ');

            /*Execute command with pars*/
            if(execCommand(ptr_sCmdPars))
                fprintf(stderr, "Error when executing command: %s\n", ptr_sCmdPars[0]);
        }
    }

    return NOERROR; /*never gets here -> see exit command*/
}

/**
 * Get input from the command line.
 *
 * @param ptr_sCmdLine Pointer to a string variable which holds the input.
 * @param size Size of the string variable.
 * @return 1 on error and 0 on no error.
 * @author Rik Janssen
 */
int getCommand(char *ptr_sCmdLine, int size)
{
    /*Show cursor*/
    printf("Command:> ");

    if(fgets(ptr_sCmdLine, size, stdin)) {
        if(!strcmp(ptr_sCmdLine, "\n"))
            return ERROR; /*User didn't enter anything*/
        ptr_sCmdLine[strlen(ptr_sCmdLine)-1] = '\0'; /*Replace newline with NULL char*/
        return NOERROR;
    }

    return ERROR; /*fgets failed*/
}

/**
 * Split str on character c in max amount of words.
 * After running word contains pointers to each seperate word.
 *
 * @param str String to split.
 * @param word Array of pointers. Each points to a seperate word.
 * @param max Max. amount of words.
 * @param c Character to split on.
 * @return Number of words after split.
 * @author MPNA
 */
int split(char *str, char *word[], int max, char c)
{
    int n = 0;

    do {
        while(*str==c)
            str++;

        if(!*str || n==max)
            return n;

        word[n++] = str++;

        while(*str && *str!=c)
            str++;

        if(!*str)
            return n;

        *str++='\0';

    } while(1);
}

/**
 * Get the command number.
 *
 * @param ptr_sCmd Command to look for.
 * @param ptr_iCmdNum Set this variable with the command number if command is found.
 * @return 1 on error (command not found) and 0 on no error(command found).
 * @author Rik Janssen
 */
int getCmdNum(char *ptr_sCmd, int *ptr_iCmdNum)
{
    const char sCommands[7][12] = {{"exit"}, {"connect"}, {"disconnect"}, {"info"}, {"help"}, {"upload"}, {"download"}};
    int i;

    /*Look if entered command (*ptr_sCmd) exists*/
    for(i=0; i<7; i++) {
        if(!strcasecmp(ptr_sCmd, &sCommands[i][0])) {
            *ptr_iCmdNum = i; /*Command found*/
            return NOERROR;
        }
    }

    return ERROR; /*Command not found*/
}

/**
 * Execute command with pars.
 *
 * @param ptr_sCmdPars Pointer to command and pars.
 * @return 1 on error and 0 on no error.
 * @author Rik Janssen
 */
int execCommand(char *ptr_sCmdPars[])
{
    int iCmdNum = -1; /*Default is unknown command number*/

    getCmdNum(ptr_sCmdPars[0], &iCmdNum);

    /*Execute command number*/
    switch(iCmdNum) {
        case 0:
            cmdExit();
            break;
        case 1:
            cmdConnect(ptr_sCmdPars[1]);
            break;
        case 2:
            cmdDisconnect();
            break;
        case 3:
            cmdInfo();
            break;
        case 4:
            cmdHelp(ptr_sCmdPars[1]);
            break;
        case 5:
            cmdUpload(ptr_sCmdPars[1], ptr_sCmdPars[2]);
            break;
        case 6:
            cmdDownload(ptr_sCmdPars[1], ptr_sCmdPars[2]);
            break;
        default:
            return ERROR; /*Unknown command number*/
    }

    return NOERROR;
}
